﻿using System;
using System.Windows;
using Microsoft.Devices.Sensors;
using Microsoft.Phone.Controls;
using Microsoft.Xna.Framework;

namespace AcceleroIllustrated
{
    public partial class MainPage : PhoneApplicationPage
    {
        private Accelerometer _acc;
        // Constructor
        public MainPage()
        {
            InitializeComponent();

            if (!Accelerometer.IsSupported)
            {
                statusTextBlock.Text = "Enheten støtter ikke akselerometer!";
                startButton.IsEnabled = false;
                stopButton.IsEnabled = false;
            }
 
        }

        private void startButton_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                if (_acc == null)
                {
                    _acc = new Accelerometer { TimeBetweenUpdates = TimeSpan.FromMilliseconds(20) };
                    _acc.CurrentValueChanged += accelerometer_CurrentValueChanged;
                }

                statusTextBlock.Text = "Starter akselerometer.";
                _acc.Start();
            }
            catch (Exception ex)
            {
                statusTextBlock.Text = "Klarte ikke starte akselerometer.";
            }
        }

        private void accelerometer_CurrentValueChanged(object sender, SensorReadingEventArgs<AccelerometerReading> e)
        {
            Dispatcher.BeginInvoke(() => UpdateUI(e.SensorReading));
        }

        private void stopButton_Click(object sender, RoutedEventArgs e)
        {
            if (_acc != null)
            {
                _acc.Stop();
                statusTextBlock.Text = "Akselerometeret har stanset.";
            }
        }

        private void UpdateUI(AccelerometerReading accelerometerReading)
        {
            statusTextBlock.Text = "Mottar data.";
            Vector3 acceleration = accelerometerReading.Acceleration;

            // Vis de numeriske verdiene. 
            xTextBlock.Text = "X: " + acceleration.X.ToString("0.00");
            yTextBlock.Text = "Y: " + acceleration.Y.ToString("0.00");
            zTextBlock.Text = "Z: " + acceleration.Z.ToString("0.00");

            // Vis verdiene grafisk. 
            xLine.X2 = xLine.X1 + acceleration.X * 200;
            yLine.Y2 = yLine.Y1 - acceleration.Y * 200;
            zLine.X2 = zLine.X1 - acceleration.Z * 100;
            zLine.Y2 = zLine.Y1 + acceleration.Z * 100;

            const float oppositeG = 1.00F;
            const float margin = 0.04F;
            if (DisplayUpOnHorizontalSurface(acceleration, oppositeG, margin))
                statusTextBlock.Text = "Enhet med skjerm opp på horisontal flate";

            if (DeviceIsStandingVertical(acceleration, oppositeG, margin))
                statusTextBlock.Text = "Enhet står vertikalt";

            const double gForceLimit = 1.1;
            double currentGForce = GetCombinedAcceleration(acceleration);
            if (currentGForce > gForceLimit) 
                statusTextBlock.Text = "G-kreftene er nå over " + gForceLimit;

            statusCombinedGForceTextBlock.Text = currentGForce + " G";
        }

        private double GetCombinedAcceleration(Vector3 acc)
        {
            float p = 2.0F;
            return Math.Sqrt(Math.Pow(acc.X, p) + Math.Pow(acc.Y, p) + Math.Pow(acc.Z, p));
        }

        private bool DisplayUpOnHorizontalSurface(Vector3 acceleration, float oppositeZ, float margin)
        {
            if (Math.Abs(acceleration.X) > margin || Math.Abs(acceleration.Y) > margin)
            {
                return false;
            }

            if ((acceleration.Z + oppositeZ) > margin)
            {
                return false;
            }

            return true;
        }

        private bool DeviceIsStandingVertical(Vector3 acceleration, float oppositeY, float margin)
        {
            if (Math.Abs(acceleration.X) > margin || Math.Abs(acceleration.Z) > margin)
            {
                return false;
            }

            if ((acceleration.Y + oppositeY) > margin)
            {
                return false;
            }

            return true;
        }
    }
}